home *** CD-ROM | disk | FTP | other *** search
/ Hardcore Visual Basic 5.0 (2nd Edition) / Hardcore Visual Basic 5.0 - Second Edition (1997)(Microsoft Press).iso / Code / LSTBOX~1.CTL < prev    next >
Text File  |  1997-06-14  |  35KB  |  1,037 lines

  1. VERSION 5.00
  2. Begin VB.UserControl XListBoxPlus 
  3.    ClientHeight    =   1890
  4.    ClientLeft      =   0
  5.    ClientTop       =   0
  6.    ClientWidth     =   3420
  7.    PropertyPages   =   "LstBoxPlus.ctx":0000
  8.    ScaleHeight     =   1890
  9.    ScaleWidth      =   3420
  10.    ToolboxBitmap   =   "LstBoxPlus.ctx":002A
  11.    Begin VB.ListBox lst 
  12.       BeginProperty Font 
  13.          Name            =   "MS Sans Serif"
  14.          Size            =   8.25
  15.          Charset         =   0
  16.          Weight          =   700
  17.          Underline       =   0   'False
  18.          Italic          =   0   'False
  19.          Strikethrough   =   0   'False
  20.       EndProperty
  21.       Height          =   1230
  22.       Left            =   600
  23.       TabIndex        =   0
  24.       Top             =   120
  25.       Width           =   1695
  26.    End
  27. End
  28. Attribute VB_Name = "XListBoxPlus"
  29. Attribute VB_GlobalNameSpace = False
  30. Attribute VB_Creatable = True
  31. Attribute VB_PredeclaredId = False
  32. Attribute VB_Exposed = True
  33. Attribute VB_Ext_KEY = "PropPageWizardRun" ,"Yes"
  34. Option Explicit
  35.  
  36. Public Enum EErrorListBoxPlus
  37.     eeBaseListBoxPlus = 13730   ' XListBoxPlus
  38. End Enum
  39.  
  40. Private myWidth As Integer
  41. Private myHeight As Integer
  42.  
  43. Private esmlMode As ESortModeList
  44. Private fHiToLo As Boolean
  45. Private eaAppearance As EAppearance
  46.  
  47. Private fCompletion As Boolean
  48. Private sPartial As String
  49. Private iPrevKey As Long
  50.  
  51. 'Event Declarations:
  52. Event Click()
  53. Attribute Click.VB_Description = "Occurs when the user presses and then releases a mouse button over an object."
  54. Event DblClick()
  55. Attribute DblClick.VB_Description = "Occurs when the user presses and releases a mouse button and then presses and releases it again over an object."
  56. Event KeyDown(KeyCode As Integer, Shift As Integer)
  57. Attribute KeyDown.VB_Description = "Occurs when the user presses a key while an object has the focus."
  58. Event KeyPress(KeyAscii As Integer)
  59. Attribute KeyPress.VB_Description = "Occurs when the user presses and releases an ANSI key."
  60. Event KeyUp(KeyCode As Integer, Shift As Integer)
  61. Attribute KeyUp.VB_Description = "Occurs when the user releases a key while an object has the focus."
  62. Event MouseDown(Button As Integer, Shift As Integer, x As Single, y As Single)
  63. Attribute MouseDown.VB_Description = "Occurs when the user presses the mouse button while an object has the focus."
  64. Event MouseMove(Button As Integer, Shift As Integer, x As Single, y As Single)
  65. Attribute MouseMove.VB_Description = "Occurs when the user moves the mouse."
  66. Event MouseUp(Button As Integer, Shift As Integer, x As Single, y As Single)
  67. Attribute MouseUp.VB_Description = "Occurs when the user releases the mouse button while an object has the focus."
  68. Event ItemCheck(Item As Integer)
  69. Attribute ItemCheck.VB_Description = "Occurs when a ListBox control's Style property is set to 1 (checkboxes) and an item's checkbox in the ListBox control is selected or cleared."
  70. Event OLECompleteDrag(Effect As Long)
  71. Attribute OLECompleteDrag.VB_Description = "Occurs at the OLE drag/drop source control after a manual or automatic drag/drop has been completed or canceled."
  72. Event OLEDragDrop(data As DataObject, Effect As Long, Button As Integer, Shift As Integer, x As Single, y As Single)
  73. Attribute OLEDragDrop.VB_Description = "Occurs when data is dropped onto the control via an OLE drag/drop operation, and OLEDropMode is set to manual."
  74. Event OLEDragOver(data As DataObject, Effect As Long, Button As Integer, Shift As Integer, x As Single, y As Single, State As Integer)
  75. Attribute OLEDragOver.VB_Description = "Occurs when the mouse is moved over the control during an OLE drag/drop operation, if its OLEDropMode property is set to manual."
  76. Event OLEGiveFeedback(Effect As Long, DefaultCursors As Boolean)
  77. Attribute OLEGiveFeedback.VB_Description = "Occurs at the source control of an OLE drag/drop operation when the mouse cursor needs to be changed."
  78. Event OLESetData(data As DataObject, DataFormat As Integer)
  79. Attribute OLESetData.VB_Description = "Occurs at the OLE drag/drop source control when the drop target requests data that was not provided to the DataObject during the OLEDragStart event."
  80. Event OLEStartDrag(data As DataObject, AllowedEffects As Long)
  81. Attribute OLEStartDrag.VB_Description = "Occurs when an OLE drag/drop operation is initiated either manually or automatically."
  82. Event Scroll()
  83. Attribute Scroll.VB_Description = "Occurs when you reposition the scroll box on a control."
  84.  
  85. ' Friend properties to make data structure accessible to walker
  86. Friend Property Get ListItems(i As Long) As String
  87.     ListItems = Item(i)
  88. End Property
  89.  
  90. ' NewEnum must have the procedure ID -4 in Procedure Attributes dialog
  91. ' Create a new data walker object and connect to it
  92. Public Function NewEnum() As IEnumVARIANT
  93. Attribute NewEnum.VB_UserMemId = -4
  94.     ' Create a new iterator object
  95.     Dim ListItemwalker As CListItemWalker
  96.     Set ListItemwalker = New CListItemWalker
  97.     ' Connect it with collection data
  98.     ListItemwalker.Attach Me
  99.     ' Return it
  100.     Set NewEnum = ListItemwalker.NewEnum
  101. End Function
  102.  
  103. Private Sub UserControl_Initialize()
  104.     Debug.Print "Initialize"
  105. End Sub
  106.  
  107. ' Initialize Properties for User Control
  108. Private Sub UserControl_InitProperties()
  109.     esmlMode = esmlUnsorted
  110.     fHiToLo = False
  111.     Extender.Name = UniqueControlName("list", Extender)
  112. End Sub
  113.  
  114. Private Sub UserControl_Paint()
  115.     DrawAppearance lst
  116. End Sub
  117.  
  118. ' Load property values from storage
  119. Private Sub UserControl_ReadProperties(PropBag As PropertyBag)
  120. With lst
  121.     Appearance = PropBag.ReadProperty("Appearance", ea3D)
  122.     'Current = PropBag.ReadProperty("Current", 1)
  123.     '.Columns = PropBag.ReadProperty("Columns", 0)
  124.     .BackColor = PropBag.ReadProperty("BackColor", vbWindowBackground)
  125.     .ForeColor = PropBag.ReadProperty("ForeColor", vbButtonText)
  126.     '.DataField = PropBag.ReadProperty("DataField", 0)
  127.     '.DataSource = PropBag.ReadProperty("DataSource", 0)
  128.     UserControl.Enabled = PropBag.ReadProperty("Enabled", True)
  129.     Set .Font = PropBag.ReadProperty("Font", lst.Font)
  130.     HiToLo = PropBag.ReadProperty("HiToLo", True)
  131.     SortMode = PropBag.ReadProperty("SortMode", esmlSortVal)
  132.     IntegralHeight = PropBag.ReadProperty("IntegralHeight", True)
  133.     Dim i As Integer, iListCount As Integer
  134.     iListCount = PropBag.ReadProperty("ListCount", 0)
  135.     If iListCount Then
  136.         Clear
  137.         For i = 0 To iListCount - 1
  138.             Add PropBag.ReadProperty("List" & i, sEmpty), , _
  139.                 PropBag.ReadProperty("ItemData" & i, 0)
  140.         Next
  141.     End If
  142.     Completion = PropBag.ReadProperty("Completion", False)
  143.     Set .MouseIcon = PropBag.ReadProperty("MouseIcon", Nothing)
  144.     .MousePointer = PropBag.ReadProperty("MousePointer", 0)
  145.     '.MultiSelect = PropBag.ReadProperty("MultiSelect", vbMultiSelectNone)
  146.     .OLEDragMode = PropBag.ReadProperty("OLEDragMode", 0)
  147.     .OLEDropMode = PropBag.ReadProperty("OLEDropMode", 0)
  148.     .RightToLeft = PropBag.ReadProperty("RightToLeft", False)
  149. 'TO DO: The member you have mapped to contains an array of data.
  150. '   You must supply the code to persist the array.  A prototype
  151. '   line is shown next:
  152. '   .Selected(Index) = PropBag.ReadProperty("Selected" & Index, 0)
  153.     .Text = PropBag.ReadProperty("Text", "")
  154.     '.TopIndex = PropBag.ReadProperty("TopItem", 1)
  155. End With
  156. End Sub
  157.  
  158. ' Write property values to storage
  159. Private Sub UserControl_WriteProperties(PropBag As PropertyBag)
  160. With lst
  161.     Debug.Print "WriteProperties: "
  162.     PropBag.WriteProperty "Appearance", Appearance, ea3D
  163.     'PropBag.WriteProperty "Current", Current, 1
  164.     'PropBag.WriteProperty "Columns", Columns, 1
  165.     PropBag.WriteProperty "BackColor", .BackColor, vbWindowBackground
  166.     PropBag.WriteProperty "ForeColor", .ForeColor, vbButtonText
  167.     'PropBag.WriteProperty "DataField", .DataField, 0
  168.     'PropBag.WriteProperty "DataSource", .DataSource, 0
  169.     PropBag.WriteProperty "Enabled", UserControl.Enabled, True
  170.     PropBag.WriteProperty "Font", .Font, lst.Font
  171.     PropBag.WriteProperty "HiToLo", HiToLo, True
  172.     PropBag.WriteProperty "IntegralHeight", IntegralHeight, True
  173.     PropBag.WriteProperty "SortMode", SortMode, esmlSortVal
  174.     PropBag.WriteProperty "ListCount", ListCount
  175.     Dim i As Integer
  176.     For i = 0 To ListCount - 1
  177.         PropBag.WriteProperty "List" & i, List(i)
  178.         PropBag.WriteProperty "ItemData" & i, ItemData(i)
  179.     Next
  180.     PropBag.WriteProperty "ListIndex", .ListIndex
  181.     PropBag.WriteProperty "Completion", Completion
  182.     PropBag.WriteProperty "MouseIcon", .MouseIcon, Nothing
  183.     PropBag.WriteProperty "MousePointer", .MousePointer, 0
  184.     PropBag.WriteProperty "MultiSelect", .MultiSelect, vbMultiSelectNone
  185.     PropBag.WriteProperty "OLEDragMode", .OLEDragMode, 0
  186.     PropBag.WriteProperty "OLEDropMode", .OLEDropMode, 0
  187.     PropBag.WriteProperty "RightToLeft", .RightToLeft, False
  188. 'TO DO: The member you have mapped to contains an array of data.
  189. '   You must supply the code to persist the array.  A prototype
  190. '   line is shown next:
  191. '   PropBag.WriteProperty "Selected" & Index, .Selected(Index), 0
  192.     PropBag.WriteProperty "Text", .Text, ""
  193.     'PropBag.WriteProperty "TopItem", .TopIndex, 1
  194. End With
  195. End Sub
  196.  
  197. Private Sub UserControl_Resize()
  198.     Static fInside As Boolean
  199.     If fInside Then Exit Sub
  200.     fInside = True
  201.     ' Adjust control to ListBox
  202.     lst.Move 0, 0, Width, Height
  203.     ' But ListBox height is in item increments, so adjust again
  204.     Height = lst.Height
  205.     Width = lst.Width
  206.     myHeight = Height
  207.     myWidth = Width
  208.     fInside = False
  209. End Sub
  210.  
  211. Private Sub UserControl_Show()
  212.     ' Handle List?
  213.     Randomize
  214. End Sub
  215.  
  216. ''' Public Methods Unique to This Class '''
  217.     
  218. ' Collection Methods
  219.  
  220. ' Add ignores the optional iPos argument except in unsorted mode.
  221. ' You cannot specify the insert position with a sorted list as you can with an unsorted list.
  222. ' Also, you cannot insert an item that already exists into a sorted
  223. ' list. A request to do so will generate an error.
  224. Sub Add(sItem As String, Optional iPos As Integer = 1, Optional iItemData As Long)
  225. With lst
  226.     ' Adding differs depending on the mode
  227.     Select Case esmlMode
  228.     Case esmlUnsorted
  229.         ' Add where directed (start is default)
  230.         .AddItem sItem, iPos - 1
  231.     Case esmlShuffle
  232.         ' Add at random position
  233.         iPos = GetRandom(0, .ListCount - 1)
  234.         If .ListCount Then
  235.             .AddItem sItem, iPos
  236.         Else
  237.             .AddItem sItem
  238.         End If
  239.         
  240.     Case Else   ' Some kind of sorting
  241.         ' Binary search for the item
  242.         If BSearch(sItem, iPos) Then
  243.             ErrRaise eseDuplicateNotAllowed
  244.         Else
  245.             ' Insert at sorted position
  246.             If .ListCount Then
  247.                 .AddItem sItem, iPos
  248.             Else
  249.                 .AddItem sItem
  250.             End If
  251.         End If
  252.     End Select
  253.     .ItemData(.NewIndex) = iItemData
  254.     PropertyChanged "List"
  255. End With
  256. End Sub
  257.  
  258. ' Same as RemoveItem but has collection name and is 1-based
  259. Sub Remove(ByVal vIndex As Variant)
  260.     If VarType(vIndex) = vbString Then
  261.         vIndex = Match(vIndex)
  262.         If vIndex = 0 Then ErrRaise eseItemNotFound
  263.     Else
  264.         If vIndex > Count Or vIndex < 1 Then ErrRaise eseOutOfRange
  265.     End If
  266.     lst.RemoveItem vIndex - 1
  267. End Sub
  268.  
  269. ' AddItem and RemoveItem are 0-based for compatibility
  270. Sub AddItem(sItem As String, Optional iPos As Integer, Optional iItemData As Long)
  271.     Add sItem, iPos + 1, iItemData
  272. End Sub
  273.  
  274. Sub RemoveItem(vIndex As Variant)
  275.     If VarType(vIndex) = vbString Then
  276.         Remove vIndex
  277.     Else
  278.         Remove vIndex + 1
  279.     End If
  280. End Sub
  281.  
  282. ' Similar to List property
  283. Property Get Item(ByVal vIndex As Variant) As String
  284. Attribute Item.VB_UserMemId = 0
  285.     If VarType(vIndex) <> vbString Then
  286.         ' For numeric index, return string value
  287.         Item = lst.List(vIndex - 1)
  288.     Else
  289.         ' For string index, return matching index or 0 for none
  290.         Item = Match(vIndex)
  291.         If Item = 0 Then ErrRaise eseItemNotFound
  292.     End If
  293. End Property
  294.  
  295. Property Let Item(ByVal vIndex As Variant, sItemA As String)
  296.     ' For string index, look up matching index
  297.     If VarType(vIndex) = vbString Then
  298.         vIndex = Match(vIndex)
  299.         ' Fail if old item isn't found or if new item is found
  300.         If vIndex = 0 Then ErrRaise eseItemNotFound
  301.     End If
  302.     If Match(sItemA) Then ErrRaise eseDuplicateNotAllowed
  303.     ' Assign value by removing old and inserting new
  304.     Remove vIndex
  305.     Add sItemA
  306.     PropertyChanged "List"
  307. End Property
  308.  
  309. ''' Public Properties Unique to This Class '''
  310.  
  311. Property Let HiToLo(fHiToLoA As Boolean)
  312.     fHiToLo = fHiToLoA
  313.     Select Case esmlMode
  314.     Case esmlUnsorted, esmlShuffle
  315.         ' Leave as is
  316.     Case Else   ' Some kind of sorting
  317.         Sort 0, lst.ListCount - 1
  318.     End Select
  319. End Property
  320.  
  321. Property Get HiToLo() As Boolean
  322.     HiToLo = fHiToLo
  323. End Property
  324.  
  325. Property Let SortMode(esmlModeA As ESortModeList)
  326.     esmlMode = esmlModeA
  327.     Select Case esmlMode
  328.     Case esmlUnsorted
  329.         ' Leave everything as is
  330.     Case esmlShuffle
  331.         Shuffle
  332.     Case Else   ' Some kind of sorting
  333.         Sort 0, lst.ListCount - 1
  334.     End Select
  335. End Property
  336.  
  337. Property Get SortMode() As ESortModeList
  338.     SortMode = esmlMode
  339. End Property
  340.  
  341. ' Gives away the store for iteration
  342. Property Get Items() As Collection
  343.     Set Items = lst
  344. End Property
  345.  
  346. ' Collection name
  347. Property Get Count() As Integer
  348.     Count = lst.ListCount
  349. End Property
  350.  
  351. Property Get Current() As Variant
  352. Attribute Current.VB_MemberFlags = "400"
  353.     Current = lst.ListIndex + 1
  354. End Property
  355.  
  356. Property Let Current(vIndexA As Variant)
  357.     If lst.ListCount = 0 Then Exit Property
  358.     If VarType(vIndexA) <> vbString Then
  359.         lst.ListIndex = vIndexA - 1
  360.     Else
  361.         lst.ListIndex = Match(vIndexA) - 1
  362.     End If
  363.     If lst.ListIndex = -1 Then ErrRaise eseItemNotFound
  364. End Property
  365.  
  366. Property Get IndexItem() As Variant
  367.     IndexItem = lst.List(lst.ListIndex)
  368. End Property
  369.  
  370. ' 1-based versions of ItemData
  371. Property Get data(i As Integer) As Variant
  372.     data = lst.ItemData(i - 1)
  373. End Property
  374.  
  375. Property Let data(i As Integer, vData As Variant)
  376.     lst.ItemData(i - 1) = vData
  377. End Property
  378.  
  379. ''' Public Methods From Contained Class '''
  380. Public Sub Clear()
  381. Attribute Clear.VB_Description = "Clears the contents of a control or the system Clipboard."
  382.     lst.Clear
  383. End Sub
  384.  
  385. Sub Drag(Optional vAction As Variant)
  386.     If IsMissing(vAction) Then
  387.         lst.Drag
  388.     Else
  389.         lst.Drag vAction
  390.     End If
  391. End Sub
  392.  
  393. Sub Move(x As Variant, Optional y As Variant, Optional dx As Variant, Optional dy As Variant)
  394.     If IsMissing(y) Then
  395.         lst.Move x
  396.     ElseIf IsMissing(dx) Then
  397.         lst.Move x, y
  398.     ElseIf IsMissing(dy) Then
  399.         lst.Move x, y, dx
  400.     Else
  401.         lst.Move x, y, dx, dy
  402.     End If
  403. End Sub
  404.  
  405. Public Sub Refresh()
  406. Attribute Refresh.VB_Description = "Forces a complete repaint of a object."
  407.     lst.Refresh
  408. End Sub
  409.  
  410. Sub SetFocus()
  411.     lst.SetFocus
  412. End Sub
  413.  
  414. Sub ZOrder(Optional vPosition As Variant)
  415.     If IsMissing(vPosition) Then
  416.         lst.ZOrder
  417.     Else
  418.         lst.ZOrder vPosition
  419.     End If
  420. End Sub
  421.  
  422. Public Property Let Completion(fCompletionA As Boolean)
  423. Attribute Completion.VB_Description = "Enables/disables word completion."
  424.     If fCompletion = False And fCompletionA = True Then
  425.         sPartial = sEmpty
  426.     End If
  427.     fCompletion = fCompletionA
  428.     PropertyChanged "Completion"
  429. End Property
  430. Public Property Get Completion() As Boolean
  431.     Completion = fCompletion
  432. End Property
  433.  
  434. Public Property Let PartialWord(sPartialA As String)
  435.     If fCompletion Then
  436.         sPartial = sPartialA
  437.         If (SortMode = esmlSortText) Or _
  438.            (SortMode = esmlSortBin) Then
  439.             If sPartial <> sEmpty Then
  440.                 CompleteWord
  441.             Else
  442.                 If ListIndex <> -1 Then lst.Selected(ListIndex) = False
  443.             End If
  444.         End If
  445.     End If
  446. End Property
  447. Public Property Get PartialWord() As String
  448. Attribute PartialWord.VB_Description = "Returns/sets the string to be completed."
  449. Attribute PartialWord.VB_MemberFlags = "400"
  450.     PartialWord = sPartial
  451. End Property
  452.  
  453. ''' Private Procedures Used by Class '''
  454.  
  455. Private Sub CompleteWord()
  456.     Dim iPos As Integer, cPartial As Integer, sItem As String
  457.     If BSearch(sPartial, iPos) Then
  458.         lst.Selected(iPos) = True
  459.     Else
  460.         ' Item not found. Look for possible completion
  461.         If Compare(Left$(List(iPos), Len(sPartial)), sPartial) = 0 Then
  462.             ' Found a completion
  463.             lst.Selected(iPos) = True
  464.         Else
  465.             ' Didn't find a completion
  466.             If lst.ListIndex <> -1 Then
  467.                 lst.Selected(lst.ListIndex) = False
  468.             End If
  469.         End If
  470.     End If
  471. End Sub
  472.  
  473. Private Function Match(ByVal sItem As String) As Integer
  474.     Dim iPos As Integer
  475.     Select Case esmlMode
  476.     Case esmlUnsorted, esmlShuffle
  477.         Match = LookupItem(lst, sItem) + 1
  478.     Case Else   ' Some kind of sorting
  479.         If BSearch(sItem, iPos) Then Match = iPos + 1 Else Match = 0
  480.     End Select
  481. End Function
  482.  
  483. Private Sub Sort(iFirst As Integer, iLast As Integer)
  484.     Dim vSplit As Variant
  485.  
  486.     If iFirst < iLast Then
  487.  
  488.         ' Only two elements in this subdivision. Exchange if
  489.         ' they are out of order, and end recursive calls.
  490.         If iLast - iFirst = 1 Then
  491.             If Compare(lst.List(iFirst), lst.List(iLast)) > 0 Then
  492.                 Swap iFirst, iLast
  493.             End If
  494.         Else
  495.  
  496.             Dim i As Integer, j As Integer, iRand As Integer
  497.  
  498.             ' Pick pivot element at random and move to end
  499.             ' (consider calling Randomize before sorting)
  500.             iRand = GetRandom(iFirst, iLast)
  501.             Swap iLast, iRand
  502.             vSplit = lst.List(iLast)
  503.             Do
  504.  
  505.                 ' Move in from both sides towards the pivot element
  506.                 i = iFirst: j = iLast
  507.                 Do While (i < j) And _
  508.                     Compare(lst.List(i), vSplit) <= 0
  509.                     i = i + 1
  510.                 Loop
  511.                 Do While (j > i) And _
  512.                     Compare(lst.List(j), vSplit) >= 0
  513.                     j = j - 1
  514.                 Loop
  515.  
  516.                 ' If we haven't reached the pivot element, it means
  517.                 ' that two elements on either side are out of order,
  518.                 ' so swap them
  519.                 If i < j Then
  520.                     Swap i, j
  521.                 End If
  522.             Loop While i < j
  523.  
  524.             ' Move the pivot element back to its proper place
  525.             Swap i, iLast
  526.  
  527.             ' Recursively call Sort (pass the smaller
  528.             ' subdivision first to use less stack space)
  529.             If (i - iFirst) < (iLast - i) Then
  530.                 Sort iFirst, i - 1
  531.                 Sort i + 1, iLast
  532.             Else
  533.                 Sort i + 1, iLast
  534.                 Sort iFirst, i - 1
  535.             End If
  536.         End If
  537.     End If
  538.  
  539. End Sub
  540.  
  541. Private Function BSearch(sKey As String, iPos As Integer) As Boolean
  542.     Dim iLo As Integer, iHi As Integer, iComp As Integer, iMid As Integer
  543.     iLo = 0: iHi = lst.ListCount - 1
  544.     Do
  545.         iMid = iLo + ((iHi - iLo) \ 2)
  546.         iComp = Compare(lst.List(iMid), sKey)
  547.         Select Case iComp
  548.         Case 0
  549.             ' Item found
  550.             iPos = iMid
  551.             BSearch = True
  552.             Exit Function
  553.         Case Is > 0
  554.             ' Item is in upper half
  555.             iHi = iMid
  556.             If iLo = iHi Then Exit Do
  557.         Case Is < 0
  558.             ' Item is in lower half
  559.             iLo = iMid + 1
  560.             If iLo > iHi Then Exit Do
  561.         End Select
  562.     Loop
  563.     ' Item not found, but return position to insert
  564.     iPos = iMid - (iComp < 0)
  565.     BSearch = False
  566.  
  567. End Function
  568.  
  569. Sub Shuffle()
  570.     Dim iFirst As Integer, iLast As Integer
  571.     iFirst = 0: iLast = lst.ListCount - 1
  572.     ' Randomize list
  573.     Dim i As Integer, v As Variant, iRnd As Integer
  574.     For i = iLast To iFirst + 1 Step -1
  575.         ' Swap random element with last element
  576.         iRnd = GetRandom(iFirst, i)
  577.         Swap i, iRnd
  578.     Next
  579. End Sub
  580.  
  581. Private Function Compare(v1 As Variant, v2 As Variant) As Integer
  582.     Dim i As Integer
  583.     If IsNumeric(v1) And IsNumeric(v2) Then
  584.         v1 = Val(v1)
  585.         v2 = Val(v2)
  586.     End If
  587.     
  588.     Select Case esmlMode
  589.     ' Sort by value (same as esmlSortBin for strings)
  590.     Case esmlSortVal
  591.         If v1 < v2 Then
  592.             i = -1
  593.         ElseIf v1 = v2 Then
  594.             i = 0
  595.         Else
  596.             i = 1
  597.         End If
  598.     ' Sort case-insensitive
  599.     Case esmlSortText
  600.         i = StrComp(v1, v2, 1)
  601.     ' Sort case-sensitive
  602.     Case esmlSortBin
  603.         i = StrComp(v1, v2, 0)
  604.     ' Sort by string length
  605.     Case esmlSortLen
  606.         If Len(v1) = Len(v2) Then
  607.             If v1 = v2 Then
  608.                 i = 0
  609.             ElseIf v1 < v2 Then
  610.                 i = -1
  611.             Else
  612.                 i = 1
  613.             End If
  614.         ElseIf Len(v1) < Len(v2) Then
  615.             i = -1
  616.         Else
  617.             i = 1
  618.         End If
  619.     End Select
  620.     If fHiToLo Then i = -i
  621.     Compare = i
  622. End Function
  623.  
  624. Sub Swap(i1 As Integer, i2 As Integer)
  625.     Dim s As String
  626.     s = lst.List(i1)
  627.     lst.List(i1) = lst.List(i2)
  628.     lst.List(i2) = s
  629. End Sub
  630.  
  631. ' Delegated properties
  632. Public Property Get BackColor() As OLE_COLOR
  633. Attribute BackColor.VB_Description = "Returns/sets the background color used to display text and graphics in an object."
  634.     BackColor = lst.BackColor
  635. End Property
  636.  
  637. Public Property Let BackColor(ByVal clrBackColor As OLE_COLOR)
  638.     lst.BackColor() = clrBackColor
  639.     PropertyChanged "BackColor"
  640. End Property
  641.  
  642. Property Get Columns() As Integer
  643.     Columns = lst.Columns
  644. End Property
  645.  
  646. Property Let Columns(iColumnsA As Integer)
  647.     lst.Columns = iColumnsA
  648.     PropertyChanged "Columns"
  649. End Property
  650.  
  651. Public Property Get Enabled() As Boolean
  652.     Enabled = UserControl.Enabled
  653. End Property
  654.  
  655. Public Property Let Enabled(ByVal fEnabled As Boolean)
  656.     UserControl.Enabled() = fEnabled
  657.     PropertyChanged "Enabled"
  658. End Property
  659.  
  660. Public Property Get ForeColor() As OLE_COLOR
  661. Attribute ForeColor.VB_Description = "Returns/sets the foreground color used to display text and graphics in an object."
  662.     ForeColor = lst.ForeColor
  663. End Property
  664.  
  665. Public Property Let ForeColor(ByVal clrForeColor As OLE_COLOR)
  666.     lst.ForeColor() = clrForeColor
  667.     PropertyChanged "ForeColor"
  668. End Property
  669.  
  670. Public Property Get Font() As Font
  671. Attribute Font.VB_Description = "Returns a Font object."
  672. Attribute Font.VB_UserMemId = -512
  673.     Set Font = lst.Font
  674. End Property
  675.  
  676. Public Property Set Font(ByVal fntFont As Font)
  677.     Set lst.Font = fntFont
  678.     PropertyChanged "Font"
  679. End Property
  680.  
  681. Property Get Appearance() As EAppearance
  682.     Appearance = eaAppearance
  683. End Property
  684.  
  685. Property Let Appearance(eaAppearanceA As EAppearance)
  686. With lst
  687.     ' Can't do this:
  688.     'lst.Appearance = eaAppearance
  689.     ' Do this instead
  690.     eaAppearance = eaAppearanceA
  691.     DrawAppearance lst
  692.     PropertyChanged "Appearance"
  693. End With
  694. End Property
  695.     
  696. Private Sub DrawAppearance(lst As ListBox)
  697. With lst
  698.     Dim rc As RECT
  699.     
  700. '    UserControl_Resize
  701. '    rc.Left = 0
  702. '    rc.Top = 0
  703. '    rc.Right = myWidth
  704. '    rc.bottom = myHeight
  705. '    Dim iScaleOld As Integer
  706. '    iScaleOld = .Parent.ScaleMode
  707. '    .Parent.ScaleMode = vbPixels
  708. '    If eaAppearance = eaFlat Then
  709. '        'DrawEdge hDC, rc, EDGE_RAISED, BF_ADJUST
  710. '        DrawEdge .Parent.hDC, rc, 0, BF_RECT
  711. '    Else
  712. '    Dim bdrFlags As Long, stlFlags As Long
  713. '    bdrFlags = bdrFlags Or BDR_RAISEDOUTER
  714. '    bdrFlags = bdrFlags Or BDR_RAISEDINNER
  715. '    bdrFlags = bdrFlags Or BDR_RAISED
  716. '    bdrFlags = bdrFlags Or BDR_SUNKEN
  717. '    bdrFlags = bdrFlags Or BDR_SUNKENOUTER
  718. '    bdrFlags = bdrFlags Or BDR_SUNKENINNER
  719. '    DrawEdge .Parent.hDC, rc, EDGE_SUNKEN, BF_RECT
  720. '    End If
  721. '    .Parent.ScaleMode = iScaleOld
  722.     Debug.Print "DrawAppearance"
  723. End With
  724. End Sub
  725.  
  726. Public Property Get hWnd() As Long
  727. Attribute hWnd.VB_Description = "Returns a handle (from Microsoft Windows) to an object's window."
  728.     hWnd = lst.hWnd
  729. End Property
  730.  
  731. Public Property Get ItemData(Index As Integer) As Long
  732. Attribute ItemData.VB_Description = "Returns/sets a specific number for each item in a ComboBox or ListBox control."
  733. Attribute ItemData.VB_ProcData.VB_Invoke_Property = "List"
  734.     ItemData = lst.ItemData(Index)
  735. End Property
  736.  
  737. Public Property Let ItemData(Index As Integer, ByVal iItemData As Long)
  738.     lst.ItemData(Index) = iItemData
  739.     PropertyChanged "ItemData"
  740. End Property
  741.  
  742. Public Property Get IntegralHeight() As Boolean
  743.     'IntegralHeight = lst.IntegralHeight
  744.     IntegralHeight = GetStyleBits(lst.hWnd) And LBS_NOINTEGRALHEIGHT
  745. End Property
  746.  
  747. Public Property Let IntegralHeight(ByVal fIntegralHeight As Boolean)
  748.     ' Can't do this:
  749.     'lst.IntegralHeight = fIntegralHeight
  750.     ' Do this instead
  751.     ChangeStyleBit lst.hWnd, fIntegralHeight, LBS_NOINTEGRALHEIGHT
  752.     PropertyChanged "IntegralHeight"
  753. End Property
  754.  
  755. ' For compatibility
  756. Public Property Get List(Index As Integer) As String
  757. Attribute List.VB_Description = "Returns/sets the items contained in a control's list portion."
  758. Attribute List.VB_ProcData.VB_Invoke_Property = "List;List"
  759.     List = lst.List(Index)
  760. End Property
  761.  
  762. Public Property Let List(Index As Integer, ByVal sList As String)
  763.     lst.List(Index) = sList
  764.     PropertyChanged "List"
  765. End Property
  766.  
  767. ' For compatibility
  768. Public Property Get ListCount() As Integer
  769. Attribute ListCount.VB_Description = "Returns the number of items in the list portion of a control."
  770.     ListCount = lst.ListCount
  771. End Property
  772.  
  773. ' For compatibility
  774. Public Property Get ListIndex() As Integer
  775. Attribute ListIndex.VB_Description = "Returns/sets the index of the currently selected item in the control."
  776. Attribute ListIndex.VB_MemberFlags = "400"
  777.     ListIndex = lst.ListIndex
  778. End Property
  779.  
  780. Public Property Let ListIndex(ByVal iListIndex As Integer)
  781.     lst.ListIndex() = iListIndex
  782.     PropertyChanged "ListIndex"
  783. End Property
  784.  
  785. Public Property Get MouseIcon() As Picture
  786. Attribute MouseIcon.VB_Description = "Sets a custom mouse icon."
  787.     Set MouseIcon = lst.MouseIcon
  788. End Property
  789.  
  790. Public Property Set MouseIcon(ByVal picMouseIcon As Picture)
  791.     Set lst.MouseIcon = picMouseIcon
  792.     PropertyChanged "MouseIcon"
  793. End Property
  794.  
  795. Public Property Get MousePointer() As MousePointerConstants
  796. Attribute MousePointer.VB_Description = "Returns/sets the type of mouse pointer displayed when over part of an object."
  797.     MousePointer = lst.MousePointer
  798. End Property
  799.  
  800. Public Property Let MousePointer(ByVal ordMousePointer As MousePointerConstants)
  801.     lst.MousePointer() = ordMousePointer
  802.     PropertyChanged "MousePointer"
  803. End Property
  804.  
  805. Public Property Get MultiSelect() As MultiSelectConstants
  806. Attribute MultiSelect.VB_Description = "Returns/sets a value that determines whether a user can make multiple selections in a control."
  807.     Dim af As Long
  808.     af = GetStyleBits(lst.hWnd)
  809.     If af And LBS_MULTIPLESEL Then
  810.         MultiSelect = vbMultiSelectSimple
  811.     ElseIf af And LBS_EXTENDEDSEL Then
  812.         MultiSelect = vbMultiSelectExtended
  813.     Else
  814.         MultiSelect = vbMultiSelectNone
  815.     End If
  816.     'MultiSelect = lst.MultiSelect
  817. End Property
  818.  
  819. Property Let MultiSelect(ordMultiSelectA As MultiSelectConstants)
  820. '    lst.MultiSelect = ordMultiSelectA
  821.     Select Case ordMultiSelectA
  822.     Case vbMultiSelectNone
  823.         ChangeStyleBit lst.hWnd, False, LBS_MULTIPLESEL
  824.         ChangeStyleBit lst.hWnd, False, LBS_EXTENDEDSEL
  825.     Case vbMultiSelectSimple
  826.         ChangeStyleBit lst.hWnd, True, LBS_MULTIPLESEL
  827.         ChangeStyleBit lst.hWnd, False, LBS_EXTENDEDSEL
  828.     Case vbMultiSelectExtended
  829.         ChangeStyleBit lst.hWnd, False, LBS_MULTIPLESEL
  830.         ChangeStyleBit lst.hWnd, True, LBS_EXTENDEDSEL
  831.     End Select
  832.     lst.Refresh
  833.     PropertyChanged "IntegralHeight"
  834. End Property
  835.  
  836. Public Property Get NewIndex() As Integer
  837. Attribute NewIndex.VB_Description = "Returns the index of the item most recently added to a control."
  838.     NewIndex = lst.NewIndex
  839. End Property
  840.  
  841. Public Property Get OLEDragMode() As Integer
  842. Attribute OLEDragMode.VB_Description = "Returns/Sets whether this object can act as an OLE drag/drop source, and whether this process is started automatically or under programmatic control."
  843.     OLEDragMode = lst.OLEDragMode
  844. End Property
  845.  
  846. Public Property Let OLEDragMode(ByVal iOLEDragMode As Integer)
  847.     lst.OLEDragMode() = iOLEDragMode
  848.     PropertyChanged "OLEDragMode"
  849. End Property
  850.  
  851. Public Property Get OLEDropMode() As Integer
  852. Attribute OLEDropMode.VB_Description = "Returns/Sets whether this object can act as an OLE drop target."
  853.     OLEDropMode = lst.OLEDropMode
  854. End Property
  855.  
  856. Public Property Let OLEDropMode(ByVal iOLEDropMode As Integer)
  857.     lst.OLEDropMode() = iOLEDropMode
  858.     PropertyChanged "OLEDropMode"
  859. End Property
  860.  
  861. Public Property Get RightToLeft() As Boolean
  862. Attribute RightToLeft.VB_Description = "Determines text display direction and control visual appearance on a bidirectional system."
  863.     RightToLeft = lst.RightToLeft
  864. End Property
  865.  
  866. Public Property Let RightToLeft(ByVal fRightToLeft As Boolean)
  867.     lst.RightToLeft() = fRightToLeft
  868.     PropertyChanged "RightToLeft"
  869. End Property
  870.  
  871. Public Property Get SelCount() As Integer
  872. Attribute SelCount.VB_Description = "Returns the number of selected items in a ListBox control."
  873.     SelCount = lst.SelCount
  874. End Property
  875.  
  876. Public Property Get Selected(Index As Integer) As Boolean
  877. Attribute Selected.VB_Description = "Returns/sets the selection status of an item in a control."
  878.     Selected = lst.Selected(Index)
  879. End Property
  880.  
  881. Public Property Let Selected(Index As Integer, ByVal fSelected As Boolean)
  882.     lst.Selected(Index) = fSelected
  883.     PropertyChanged "Selected"
  884. End Property
  885.  
  886. Public Property Get Text() As String
  887. Attribute Text.VB_Description = "Returns/sets the text contained in the control."
  888. Attribute Text.VB_MemberFlags = "424"
  889.     Text = lst.Text
  890. End Property
  891.  
  892. Public Property Let Text(ByVal sText As String)
  893.     lst.Text() = sText
  894.     PropertyChanged "Text"
  895. End Property
  896.  
  897. Public Property Get TopItem() As Integer
  898. Attribute TopItem.VB_Description = "Returns/sets which item in a control is displayed in the topmost position."
  899. Attribute TopItem.VB_MemberFlags = "400"
  900.     TopItem = lst.TopIndex
  901. End Property
  902.  
  903. Public Property Let TopItem(ByVal iTopItem As Integer)
  904.     lst.TopIndex() = iTopItem
  905.     PropertyChanged "TopItem"
  906. End Property
  907.  
  908. ' Delegated methods
  909.  
  910. Public Sub OLEDrag()
  911. Attribute OLEDrag.VB_Description = "Starts an OLE drag/drop event with the given control as the source."
  912.     lst.OLEDrag
  913. End Sub
  914.  
  915. ' Event delegators
  916. Private Sub lst_Click()
  917.     RaiseEvent Click
  918. End Sub
  919.  
  920. Private Sub lst_DblClick()
  921.     RaiseEvent DblClick
  922. End Sub
  923.  
  924. Private Sub lst_KeyDown(KeyCode As Integer, Shift As Integer)
  925.     RaiseEvent KeyDown(KeyCode, Shift)
  926. End Sub
  927.  
  928. Private Sub lst_KeyPress(KeyAscii As Integer)
  929.     Static msPrevKeyPress As Long
  930.     Dim msCurKeyPress As Long, iKey As Integer
  931.     iKey = KeyAscii
  932.     If fCompletion Then
  933.         msCurKeyPress = GetTickCount
  934.         ' Check time between keypresses
  935.         If (msCurKeyPress - msPrevKeyPress) >= 1000 Then
  936.             sPartial = sEmpty
  937.         End If
  938.         ' Handle special case keys
  939.         Select Case iKey
  940.         Case vbKeyBack
  941.             ' Handle backspace
  942.             If Len(sPartial) Then
  943.                 PartialWord = Left$(sPartial, Len(sPartial) - 1)
  944.             End If
  945.         Case Is >= vbKeySpace
  946.             ' For ASCII keys add keystroke to current partial word
  947.             PartialWord = sPartial & Chr$(iKey)
  948.         Case Else
  949.             ' Ignore other control keys
  950.         End Select
  951.         msPrevKeyPress = msCurKeyPress
  952.         ' Default text box behavior interferes with
  953.         ' word completion, so throw away all keypresses
  954.         KeyAscii = 0
  955.     End If
  956.     RaiseEvent KeyPress(iKey)
  957. End Sub
  958.  
  959. Private Sub UserControl_KeyPress(KeyAscii As Integer)
  960.     'RaiseEvent KeyPress(KeyAscii)
  961. End Sub
  962.  
  963. Private Sub lst_KeyUp(KeyCode As Integer, Shift As Integer)
  964.     RaiseEvent KeyUp(KeyCode, Shift)
  965. End Sub
  966.  
  967. Private Sub lst_MouseDown(Button As Integer, Shift As Integer, x As Single, y As Single)
  968.     RaiseEvent MouseDown(Button, Shift, x, y)
  969. End Sub
  970.  
  971. Private Sub lst_MouseMove(Button As Integer, Shift As Integer, x As Single, y As Single)
  972.     RaiseEvent MouseMove(Button, Shift, x, y)
  973. End Sub
  974.  
  975. Private Sub lst_MouseUp(Button As Integer, Shift As Integer, x As Single, y As Single)
  976.     RaiseEvent MouseUp(Button, Shift, x, y)
  977. End Sub
  978.  
  979. Private Sub lst_ItemCheck(Item As Integer)
  980.     RaiseEvent ItemCheck(Item)
  981. End Sub
  982.  
  983. Private Sub lst_OLECompleteDrag(Effect As Long)
  984.     RaiseEvent OLECompleteDrag(Effect)
  985. End Sub
  986.  
  987. Private Sub lst_OLEDragDrop(data As DataObject, Effect As Long, Button As Integer, Shift As Integer, x As Single, y As Single)
  988.     RaiseEvent OLEDragDrop(data, Effect, Button, Shift, x, y)
  989. End Sub
  990.  
  991. Private Sub lst_OLEDragOver(data As DataObject, Effect As Long, Button As Integer, Shift As Integer, x As Single, y As Single, State As Integer)
  992.     RaiseEvent OLEDragOver(data, Effect, Button, Shift, x, y, State)
  993. End Sub
  994.  
  995. Private Sub lst_OLEGiveFeedback(Effect As Long, DefaultCursors As Boolean)
  996.     RaiseEvent OLEGiveFeedback(Effect, DefaultCursors)
  997. End Sub
  998.  
  999. Private Sub lst_OLESetData(data As DataObject, DataFormat As Integer)
  1000.     RaiseEvent OLESetData(data, DataFormat)
  1001. End Sub
  1002.  
  1003. Private Sub lst_OLEStartDrag(data As DataObject, AllowedEffects As Long)
  1004.     RaiseEvent OLEStartDrag(data, AllowedEffects)
  1005. End Sub
  1006.  
  1007. Private Sub lst_Scroll()
  1008.     RaiseEvent Scroll
  1009. End Sub
  1010.  
  1011. Private Sub ErrRaise(e As Long)
  1012.     Dim sText As String, sSource As String
  1013.     If e > 1000 Then
  1014.         sSource = App.EXEName
  1015.         Select Case e
  1016.         Case eseNone
  1017.             BugAssert True
  1018.         Case eseItemNotFound
  1019.             sText = "Item not in list"
  1020.         Case eseOutOfRange
  1021.             sText = "Index out of range"
  1022.         Case eseDuplicateNotAllowed
  1023.             sText = "Duplicate entries not allowed"
  1024.         End Select
  1025.         Err.Raise COMError(e), sSource, sText
  1026.     Else
  1027.         ' Raise standard Visual Basic error
  1028.         sSource = App.EXEName & ".VBError"
  1029.         Err.Raise e, sSource
  1030.     End If
  1031. End Sub
  1032.  
  1033. 'Private Function GetRandom(ByVal iLo As Long, ByVal iHi As Long) As Long
  1034. '    GetRandom = Int(iLo + (Rnd * (iHi - iLo + 1)))
  1035. 'End Function
  1036.  
  1037.